package com.yex.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.yex.common.utils.PageUtils;
import com.yex.dao.UserDao;
import com.yex.entity.*;
import com.yex.service.*;
import com.yex.utils.JsonResultVo;
import com.yex.utils.Query;
import com.yex.utils.Utils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;


@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {
    @Autowired
    private TokenService tokenService;
    @Autowired
    private LocaleMessageSourceService message;
    @Autowired
    private WalletService walletService;
    @Autowired
    private InvestService investService;
    @Autowired
    private IntegralService integralService;
    @Autowired
    private SysConfigService sysConfigService;


    @Override
    public PageUtils queryPage(Map<String, Object> params, String filter) {
        Page<UserEntity> page = new Query<UserEntity>(params).getPage();
        List<UserEntity> userEntityList = baseMapper.selectPageFilter(page, filter);
        page.setRecords(userEntityList);
        return new PageUtils(page);
    }

    @Override
    public PageUtils merchantPage(Map<String, Object> params) {
        Page<UserEntity> page = new Query<UserEntity>(params).getPage();
        EntityWrapper<UserEntity> wrapper = new EntityWrapper<>();
        wrapper.eq("merchant_state", 1);
        List<UserEntity> userEntityList = baseMapper.selectPage(page, wrapper);
        page.setRecords(userEntityList);
        return new PageUtils(page);
    }

    public void merchantGranted(Long[] ids) {
        EntityWrapper<UserEntity> wrapper = new EntityWrapper<>();
        wrapper.eq("merchant_state", 1).in("id", ids);
        UserEntity userEntity = new UserEntity();
        userEntity.setMerchantState(2);
        baseMapper.update(userEntity, wrapper);
    }

    @Override
    public UserEntity selectUserByMobile(String mobile) {
        return baseMapper.selectUserByMobile(mobile);
    }

    @Override
    public UserEntity selectUserByMobileOrUid(String mobile) {
        return baseMapper.selectUserByMobileOrUid(mobile);
    }

    @Override
    public List<UserEntity> selectUserByIdentityNumber(String identityNumber) {
        return baseMapper.selectUserByIdentityNumber(identityNumber);
    }


    @Override
    @Transactional
    public JsonResultVo insertUser(String mobile, String area, Integer introUserid, String password, String ip) {
        UserEntity userEntity = new UserEntity();
        password = DigestUtils.sha256Hex(password);
        userEntity.setShare(Utils.randomUpperString(1)+Utils.randomInteger(4));
        userEntity.setUsername(mobile);
        userEntity.setMobile(mobile);
        userEntity.setPassword(password);
        userEntity.setIntroUserid(introUserid);
        userEntity.setCreateTime(new Date());
        userEntity.setUpdateTime(new Date());
        userEntity.setLoginTime(new Date());
        userEntity.setLoginIp(ip);
        userEntity.setRegisterTime(new Date());
        userEntity.setStatus(1);
        userEntity.setArea(area);
        userEntity.setLeader(0);
        userEntity.setLeaderRate(BigDecimal.ZERO);
        Integer result = baseMapper.insert(userEntity);
        Map<String, Object> map = new HashMap<>(2);

        if (introUserid != null) {
            Integer result1 = baseMapper.updateIntroUserCount(introUserid);
            if (result1 <= 0) {
                return new JsonResultVo(message.getMessage("fail"), -1);
            }
        }

        if (result > 0) {
            TokenEntity tokenEntity = tokenService.createToken(userEntity.getId());
            if (tokenEntity == null) {
                throw new RuntimeException(message.getMessage("fail"));
            }
            map.put("token", tokenEntity.getToken());
            map.put("expire", tokenEntity.getExpireTime().getTime() - System.currentTimeMillis());
            map.put("username", userEntity.getUsername());
            map.put("mobile", userEntity.getMobile());
            map.put("photo", userEntity.getPhoto());
            map.put("realName", userEntity.getRealName());
            map.put("identityNumber", userEntity.getIdentityNumber());
            map.put("identityPath", userEntity.getIdentityPath());
            map.put("isMoneyPassword", StringUtils.isNotBlank(userEntity.getIdentityPath()));
            map.put("realValidate", userEntity.getRealValidate());
            map.put("identityType", userEntity.getIdentityType());
            map.put("validateStatus", userEntity.getValidateStatus());
            map.put("introUserCount", userEntity.getIntroUserCount());
        }

        WalletEntity walletEntity = new WalletEntity();
        walletEntity.setUserId(userEntity.getId());
        walletEntity.setFrozen(BigDecimal.valueOf(0));
        walletEntity.setTotal(BigDecimal.valueOf(0));
        walletEntity.setCreateTime(new Date());
        walletEntity.setUpdateTime(new Date());
        walletService.insert(walletEntity);

        return result > 0 ? new JsonResultVo(message.getMessage("success"), map, 0) : new JsonResultVo(message.getMessage("fail"), -1);
    }

    @Override
    public JsonResultVo selectIntroList(Integer userId) {
        List<UserEntity> userEntityList = baseMapper.selectIntroUserId(userId);
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (UserEntity userEntity : userEntityList) {
            Map<String, Object> map = new HashMap<>(5);
            String realName = userEntity.getRealName();
            if (StringUtils.isBlank(realName)) realName = userEntity.getUsername();
            map.put("id", userEntity.getId());
            map.put("photo", sysConfigService.getValue("url") + userEntity.getPhoto());
            map.put("mobile", userEntity.getMobile());
            map.put("realName", realName);
            mapList.add(map);
        }
        return new JsonResultVo(message.getMessage("success"), mapList, 0);
    }

    @Override
    @Transactional
    public Integer updateUserPhoto(String path, Integer userId) {

        return baseMapper.updateUserPhoto(path, userId);

    }

    @Override
    @Transactional
    public JsonResultVo updateRealNameAuth(UserEntity userEntity) {
        return baseMapper.updateById(userEntity) > 0 ? new JsonResultVo(message.getMessage("success")) : new JsonResultVo(message.getMessage("fail"), -1);
    }


    @Override
    @Transactional
    public JsonResultVo updateUserByLogin(String mobile, String password, String ip) {
        password = DigestUtils.sha256Hex(password);

        UserEntity userEntity = baseMapper.selectUserByLogin(mobile, password);

        if (userEntity == null) {
            return new JsonResultVo(message.getMessage("username_not_exist"), -1);
        }

        Integer result = baseMapper.updateUserByLogin(userEntity.getId(), ip);
        if (result <= 0) {
            return new JsonResultVo(message.getMessage("fail"), -1);
        }

        TokenEntity tokenEntity = tokenService.createToken(userEntity.getId());
        if (tokenEntity == null) {
            throw new RuntimeException(message.getMessage("fail"));
        }
        Map<String, Object> map = new HashMap<>(2);
        map.put("token", tokenEntity.getToken());
        map.put("expire", tokenEntity.getExpireTime().getTime() - System.currentTimeMillis());
        map.put("username", userEntity.getUsername());
        map.put("mobile", userEntity.getMobile());
        map.put("photo", userEntity.getPhoto());
        map.put("realName", userEntity.getRealName());
        map.put("identityNumber", userEntity.getIdentityNumber());
        map.put("identityPath", userEntity.getIdentityPath());
        map.put("realValidate", userEntity.getRealValidate());
        map.put("isMoneyPassword", StringUtils.isNotBlank(userEntity.getMoneyPassword()));
        map.put("identityType", userEntity.getIdentityType());
        map.put("validateStatus", userEntity.getValidateStatus());
        map.put("introUserCount", userEntity.getIntroUserCount());
        map.put("id", userEntity.getId());

        return result > 0 ? new JsonResultVo(message.getMessage("success"), map, 0) : new JsonResultVo(message.getMessage("fail"), -1);
    }

    @Override
    @Transactional
    public JsonResultVo updateForgetPassword(String mobile, String password) {

        password = DigestUtils.sha256Hex(password);
        UserEntity userEntity = baseMapper.selectUserByMobile(mobile);
        if (userEntity == null) {
            return new JsonResultVo(message.getMessage("fail"), -1);
        }

        Integer result = baseMapper.updateModifyPassword(userEntity.getId(), password);

        return result > 0 ? new JsonResultVo(message.getMessage("success")) : new JsonResultVo(message.getMessage("fail"), -1);
    }

    @Override
    @Transactional
    public JsonResultVo updateMoneyPassword(UserEntity userEntity, String password) {
        password = DigestUtils.sha256Hex(password);
        Integer result = baseMapper.updateMoneyPassword(userEntity.getId(), password);
        return result > 0 ? new JsonResultVo(message.getMessage("success")) : new JsonResultVo(message.getMessage("fail"), -1);
    }

    @Override
    @Transactional
    public JsonResultVo updateModifyPassword(UserEntity userEntity, String password) {
        password = DigestUtils.sha256Hex(password);
        Integer result = baseMapper.updateModifyPassword(userEntity.getId(), password);

        return result > 0 ? new JsonResultVo(message.getMessage("success")) : new JsonResultVo(message.getMessage("fail"), -1);
    }

    @Override
    @Transactional
    public Integer updatePassIdentity(Integer userId) {
        Integer result = baseMapper.updatePassIdentity(userId);
        return result > 0 ? 1 : 0;
    }

    @Override
    @Transactional
    public Integer updateNoPassIdentity(Integer userId) {
        Integer result = baseMapper.updateNoPassIdentity(userId);
        return result > 0 ? 1 : 0;
    }

    @Override
    public JsonResultVo userInfo(UserEntity userEntity) {

        Map<String, Object> map = new HashMap<>(2);
        map.put("id", userEntity.getId());
        map.put("username", userEntity.getUsername());
        map.put("share", userEntity.getShare());
        map.put("mobile", userEntity.getMobile());
        map.put("photo", sysConfigService.getValue("url") + userEntity.getPhoto());
        map.put("realName", userEntity.getRealName());
        map.put("identityNumber", userEntity.getIdentityNumber());
        map.put("identityPath", userEntity.getIdentityPath());
        map.put("realValidate", userEntity.getRealValidate());
        map.put("identityType", userEntity.getIdentityType());
        map.put("validateStatus", userEntity.getValidateStatus());
        map.put("introUserCount", userEntity.getIntroUserCount());
        map.put("isMoneyPassword", StringUtils.isNotBlank(userEntity.getMoneyPassword()));
        map.put("introDownCount", userEntity.getIntroDownCount());
        map.put("shareUrl", sysConfigService.getValue("shareUrl") + userEntity.getMobile());
        WalletEntity walletEntity = walletService.selectByUserId(userEntity.getId());
        map.put("walletTotal", 0);
        map.put("walletFrozen", 0);
        if (walletEntity != null) {
            map.put("walletTotal", walletEntity.getTotal());
            map.put("walletFrozen", walletEntity.getFrozen());
        }

        map.put("investTotal", userEntity.getTotal());
        map.put("investFrozen", userEntity.getFrozen());

//        InvestEntity investEntity = investService.selectByUserId(userEntity.getId());
//        map.put("investTotal", 0);
//        map.put("investFrozen", 0);
//        if (investEntity != null) {
//            map.put("investTotal", userEntity.getTotal());
//            map.put("investFrozen", userEntity.getFrozen());
//        }

        IntegralEntity integralEntity = integralService.selectByUserId(userEntity.getId());
        map.put("integralTotal", 0);
        map.put("integralFrozen", 0);
        if (integralEntity != null) {
            map.put("integralTotal", integralEntity.getTotal());
            map.put("integralFrozen", integralEntity.getFrozen());
        }

        return new JsonResultVo(message.getMessage("success"), map, 0);
    }

    public Map<String, Integer> getIntro(Integer userId) {
        Map<String, Integer> map = new HashMap<>(10);
        map.put("introCount", 0);
        map.put("downCount", 0);
        Map<String, Integer> introUser = getIntroUser(userId, userId, map);
        return introUser;
    }

    public Map<String, Integer> getIntroUser(Integer oldUserId, Integer userId, Map<String, Integer> str) {
        List<UserEntity> list = baseMapper.selectIntroUserId(userId);
        if (list != null && list.size() > 0) {
            if (!oldUserId.equals(userId)) {
                Integer count = str.get("downCount");
                str.put("downCount", count + list.size());
            } else {
                Integer count = str.get("introCount");
                str.put("introCount", count + list.size());
            }
            for (int i = 0; i < list.size(); i++) {
                str = getIntroUser(oldUserId, list.get(i).getId(), str);
            }
        }
        return str;
    }

    @Override
    public List<UserEntity> selectPageFilter(Page<UserEntity> page, String filter) {
        return baseMapper.selectPageFilter(page, filter);
    }

    @Override
    public List<UserEntity> selectIntroUserId(Integer introUserId) {
        return baseMapper.selectIntroUserId(introUserId);
    }

    @Override
    @Transactional
    public Integer updateIntro() {
        int loopSize = 1;
        int bacheSize = 100;
        Page<UserEntity> fuserPage = new Page<UserEntity>(loopSize, bacheSize);
        List<UserEntity> listUser = baseMapper.selectPageFilter(fuserPage, "");
        while (true) {
            try {
                for (UserEntity userEntity : listUser) {
                    Map<String, Integer> intro = getIntro(userEntity.getId());
                    Integer integer = baseMapper.updateIntroUser(userEntity.getId(), intro.get("introCount"), intro.get("downCount"));
                    System.out.println(userEntity.getId() + "==========introCount=========" + intro.get("introCount") + "==========downCount=========" + intro.get("downCount"));
                    Thread.sleep(500);
                }
                loopSize++;
                fuserPage = new Page<UserEntity>(loopSize, bacheSize);
                listUser = baseMapper.selectPageFilter(fuserPage, "");
                if (listUser == null || listUser.isEmpty()) {
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
